package com.ramble.zxing;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.charset.Charset;
import java.security.interfaces.RSAPrivateKey;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@SpringBootApplication
public class ZxingApplication {

    public static void main(String[] args) {

        //SpringApplication.run(ZxingApplication.class, args);
        try {
            String person = "1&110101199003079518";
            Long second = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
            String biz = "&1&" + Base64.encode("浙江身份码") + "&ZJSFM&" + second;

            String aesKeys = IdUtil.simpleUUID();
            log.info("aesKey is :{}", aesKeys);
            String a = AESUtils.encrypt(person, aesKeys);
            log.info("a is  :{} , length is :{}", a, a.length());
            String b = biz;
            log.info("b is  :{} , length is :{}", b, b.length());
            RSA rsa = SecureUtil.rsa();
            String s = rsa.encryptBase64(a + b, Charset.forName("utf-8"), KeyType.PrivateKey);
            log.info("s is  :{} , length is :{}", s, s.length());
            String content = a + b + s;
            log.info("content is  :{} , length is :{}", content, content.length());

            BitMatrix bitMatrix = encodeLowErrorCorrection(content);
            BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix,
                    new MatrixToImageConfig(Color.BLACK.getRGB(), Color.WHITE.getRGB()));
            String filePath = "D:\\Temp\\images/";
            String fileName = IdUtil.simpleUUID() + ".jpg";
            File outputfile = new File(filePath + fileName);
            ImageIO.write(bufferedImage, "jpg", outputfile);

        } catch (Exception e) {
            log.error("error :{}", e.getMessage());
        }


    }

    private static void saveImg(String content) {
        try {
            BitMatrix bitMatrix = encodeHighErrorCorrection(content);
            BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix,
                    new MatrixToImageConfig(Color.BLACK.getRGB(), Color.WHITE.getRGB()));
            String filePath = "D:\\Temp\\images/";
            String fileName = IdUtil.simpleUUID() + ".jpg";
            File outputfile = new File(filePath + fileName);
            ImageIO.write(bufferedImage, "jpg", outputfile);
        } catch (Exception e) {
            log.error("saveImg-error,{}", e.getMessage());
        }
    }


    /**
     * 最高纠错等级
     *
     * @param contents
     * @return
     * @throws WriterException
     */
    private static BitMatrix encodeHighErrorCorrection(String contents) throws WriterException {
        final Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        return new QRCodeWriter().encode(contents, BarcodeFormat.QR_CODE, 320, 320, hints);
    }

    /**
     * 最低纠错等级
     *
     * @param contents
     * @return
     * @throws WriterException
     */
    private static BitMatrix encodeLowErrorCorrection(String contents) throws WriterException {
        final Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        return new QRCodeWriter().encode(contents, BarcodeFormat.QR_CODE, 320, 320, hints);
    }

}
